package com.xinyue.auto;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.xinyue.auto.bean.Entity;
import com.xinyue.auto.exception.XmlException;
import com.xinyue.auto.reader.EntityReader;
import com.xinyue.auto.reader.ManyReader;
import com.xinyue.auto.reader.ParamHolder;
import com.xinyue.auto.util.StringUtil;

/**
 * 使用Dom4j解析XML文件
 * 返回EntityData类型数据，一个EntityData对象，对应XML文件中的一个entity标签
 * entity中包括一个bean、dao、daoImpl对象的所有信息
 */
public class XmlReader implements Label{
	//JAVA对象方法集合
	private List<Entity> entites = new ArrayList<Entity>();
	//参数集数据
	private ParamHolder holder = ParamHolder.getInstance();
	//文件基础路径
	private String basePkg;
	
	/**
	 * 读取所有XML配置文件中的Entity信息，并封装返回对象。
	 * @param paths
	 * @return Data类型数据
	 */
	@SuppressWarnings("unchecked")
	public void readXml(List<String> paths) throws Exception {
		SAXReader reader = new SAXReader();
		for (int i = 0; i < paths.size(); i++) {
			Element root = validate(reader, paths.get(i));
			
			//读取一个XML文件中entity标签信息
			List<Element> ens = root.elements(entity_);
			if(ens == null || ens.size() == 0) {
				throw new XmlException("文档中未定义entity标签", holder.getException());
			}
			for (Element entity: ens) {
				//刷新参数集数据
				holder.refresh(basePkg);
				//读取一个Entity标签数据
				EntityReader.getInstance().read(entity);
				Entity en = holder.getEntity();
				
				entites.add(en);
			}
			
			//读取一个Xml文件中的多对多映射many-many信息
			List<Element> manys = root.elements(many_many_);
			if(manys != null && manys.size() > 0) {
				for (Element many : manys) {
					//刷新参数集数据
					holder.refresh(basePkg);
					//读取一个many-many标签数据
					ManyReader.getInstance().read(many);
					Entity en = holder.getEntity();
					
					entites.add(en);
				}
			}
		}
	}
	
	/**
	 * 验证XML文件结构合法性，并返回XML文件ROOT标签
	 * @param reader
	 * @param path
	 * @return
	 * @throws Exception
	 */
	private Element validate(SAXReader reader, String path) throws Exception {
		//异常信息Xml文件路径
		holder.getException().setXmlPath(StringUtil.getNameByLine(path));
		
		Element root = null;
		try {
			//读取一个配置文件
			Document document = reader.read(new File(path));
			root = document.getRootElement();
		} catch (DocumentException e) {
			throw new Exception("XML文档路径无效：" + path, e);
		}
		
		Element base = root.element(base_package_);
		if(base == null) {
			throw new XmlException("未定义base-package标签或其值为空", holder.getException());
		}else {
			basePkg = base.attributeValue(package_);
			if(StringUtil.isNull(basePkg)) {
				throw new XmlException("base-package标签package属性未定义或其值为空", holder.getException());
			}
		}
		
		return root;
	}

	/**
	 * 获得实体集合
	 * @return
	 */
	public List<Entity> getEntites() {
		return entites;
	}
}